#ifndef _SERVER_H
#define _SERVER_H

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> 
#include <string.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>


#define MAX_WAIT 10
#define IP_LEN 16
#define MSG_MAX_LEN 256
#define EXIT_MASK "exit"
#define SEND_MODE_BASE  1
#define SEND_MODE_EXIT  2
#define SEND_TO_ONE 3
#define PRIVATE_CHAT       "P_Chat"
#define WE_CHAT            "W_Chat"
#define SHOW_WEATHER       "S_Weat"
#define SHOW_ONLINE_CLI    "ONLINE_Cli"



typedef struct server_info *PSI;

// 客户端链表节点结构体
typedef struct client_node{
    // 套接字
    int cli_fd;
    // 客户端IP地址
    char cli_ip[IP_LEN];
    // 服务器信息指针
    PSI ser_info;
    // 线程ID
    pthread_t cli_tid;
    // 存放客户端链表下一个节点指针和前一个节点指针
    struct client_node *next, *prev;

}CN, *PCN;


// 服务器主结构体，用于存放服务器信息
typedef struct server_info{
    // 套接字、端口号
    int ser_fd, ser_port;
    // 互斥锁
    pthread_mutex_t mutex;
    // 等待客户端连接的线程ID
    pthread_t wait_cli_tid;
    // 存放客户端链表头节点
    PCN cli_node_head;

}SI, *PSI;



void *Send(void *arg);
// 服务器初始化
PSI Server_Init(int ser_port); 
// 创建客户端节点
PCN Create_Cnode(); 
// 尾插添加客户端节点
bool Cnode_Add_Tail(PCN cli_head, PCN new_cnode);
// 删除客户端节点
bool   Del_Client_Node(PCN del_client_node);
// 等待客户端连接的线程
void *Wait_For_Client_Connect(void *arg);
// 模式选择
void *Mode_Select(void *arg);
// 服务器功能选择
bool Function_Select(PSI server_info);
// 遍历在线客户端节点返回在线IP地址
char *Show_Online_Client(PSI server_info);
// 服务器显示在线客户端UI
bool Show_Online_Client_UI(char *str);
// 发送消息给客户端
bool Send_Message_To_Client(int cli_fd, const char *message);
// 查找客户端节点
PCN Find_Client_Node(PCN cnode, char* target_ip);
// 广播任务
bool Broadcast_Task(PCN client_node);
// 发送消息给所有客户端
bool Send_All(PCN client_node, char *broadcast_msg, int send_mode);
// 私聊任务
bool Private_Task(PCN client_node, char *target_ip);
// 发送消息给指定客户端
bool Send_To_One(PCN client_node, char *private_msg, int send_mode, char *cli_ip);

bool Tcp_Broadcast_Free(PSI broadcast_inf_struct);

#endif